package com.lzc.springPart.BeanFactoryPostProcess;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

public class GetBeanPostProcess implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) {
        // 获取所有beanDefinition名称
        String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            // 拿到名称对应的beanDefinition
            BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanDefinitionName);
            // 获取className
            String beanClassName = beanDefinition.getBeanClassName();
            try {
                // 得到字节码对象
                Class<?> aClass = Class.forName(beanClassName);
                // 判断是否有configuration注解
                if (aClass.getAnnotationsByType(Configuration.class).length != 0){
                   // 有configuration 并且判断其中方法是否有@Bean注解
                    Method[] declaredMethods = aClass.getDeclaredMethods();
                    // 遍历所有方法
                    for (Method declaredMethod : declaredMethods) {
                        // 判断是否有@Bean注解
                        Bean[] annotationsBean = declaredMethod.getAnnotationsByType(Bean.class);
                        // 如果有
                        if (annotationsBean.length != 0){
                            // 将该方法作为bean定义执行
                            AbstractBeanDefinition methodBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition().setFactoryMethodOnBean(declaredMethod.getName(), beanDefinitionName)
                                    .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR) // 参数自动装配
                                    .getBeanDefinition();
                            if (configurableListableBeanFactory instanceof DefaultListableBeanFactory){
                                DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
                                beanFactory.registerBeanDefinition(declaredMethod.getName(),methodBeanDefinition);
                            }
                        }
                    }
                }
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
